unit uPrincipal;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, Grids, StdCtrls, Buttons, ExtCtrls,
  simSO, simSOCatedra, simSOAlumno, ActnList;

type
  TfrmPrincipal = class(TForm)
    mnuPrincipal: TMainMenu;
    Sistema1: TMenuItem;
    Salir1: TMenuItem;
    Ayuda1: TMenuItem;
    Acercade1: TMenuItem;
    datos1: TMenuItem;
    Procesos1: TMenuItem;
    Memoria1: TMenuItem;
    Disco1: TMenuItem;
    Dispositivos1: TMenuItem;
    Crear1: TMenuItem;
    Estados1: TMenuItem;
    N1: TMenuItem;
    N2: TMenuItem;
    GroupBox1: TGroupBox;
    gProcesosC: TStringGrid;
    GroupBox2: TGroupBox;
    gMemoria: TStringGrid;
    GroupBox3: TGroupBox;
    gDisco: TStringGrid;
    GroupBox4: TGroupBox;
    btnIniciar: TSpeedButton;
    Label1: TLabel;
    Label2: TLabel;
    Label4: TLabel;
    Label3: TLabel;
    GroupBox5: TGroupBox;
    mHisotrial: TMemo;
    imgMemoriaRead: TImage;
    imgMemoriaWrite: TImage;
    imgDiscoWrite: TImage;
    imgDiscoRead: TImage;
    imgDeadLook: TImage;
    imgFallamemoria: TImage;
    imgFallaDisco: TImage;
    imgErrorDispositivo: TImage;
    cpuClock: TTimer;
    GroupBox6: TGroupBox;
    gProcesosA: TStringGrid;
    N3: TMenuItem;
    Ejecutar1: TMenuItem;
    mnuFIFO: TMenuItem;
    mnuRR: TMenuItem;
    mnuSJN: TMenuItem;
    mnuSRT: TMenuItem;
    N4: TMenuItem;
    alMenu: TActionList;
    acClickAlgoritmo: TAction;
    procedure btnIniciarClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure cpuClockTimer(Sender: TObject);
    procedure gProcesosCDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure acClickAlgoritmoExecute(Sender: TObject);
  private
    //
  public
    procedure LeyendoMemoria;
    procedure LeyendoDisco;
    procedure EscribiendoMemoria;
    procedure EscribiendoDisco;
    procedure HayDeadLook;
    procedure HayFallaMemoria;
    procedure HayFallaDisco;
    procedure HayFallaDispositivo;
    procedure InicializarGrilla(laGrilla: TStringGrid; listaProcesos: tListaProcesos);
  end;

const
  TiempoTotal = 30;
  Quantum = 3;

var
  frmPrincipal: TfrmPrincipal;

  // Hardware
  procesador: tProcesador;
  memoria: tMemoria;
  disco: tDisco;

  // Variables generales
  ciclo: Integer;
  todosLosProcesosC: tListaProcesos;
  todosLosProcesosA: tListaProcesos;
  quantumG: Integer;

  // Variables manejadas por los alumnos
  pManagerAlumno: tManejadorProcesadorAlumno; // Manejador del procesador
  pActualAlumno: tProceso;                    // Proceso actualmente en el procesador

  // Variables manejadas por la catedra
  pManagerCatedra: tManejadorProcesadorCatedra; // Manejador del procesador
  pActualCatedra: tProceso;                    // Proceso actualmente en el procesador

implementation

{$R *.dfm}

{ TForm1 }

procedure TfrmPrincipal.EscribiendoDisco;
begin
  imgDiscoWrite.Enabled:= True;
end;

procedure TfrmPrincipal.EscribiendoMemoria;
begin
  imgMemoriaWrite.Enabled:= True;
end;

procedure TfrmPrincipal.HayDeadLook;
begin
  imgDeadLook.Enabled:= True;
end;

procedure TfrmPrincipal.HayFallaDisco;
begin
  imgFallaDisco.Enabled:= True;
end;

procedure TfrmPrincipal.HayFallaDispositivo;
begin
  imgErrorDispositivo.Enabled:= True;
end;

procedure TfrmPrincipal.HayFallaMemoria;
begin
  imgFallaMemoria.Enabled:= True;
end;

procedure TfrmPrincipal.LeyendoDisco;
begin
  imgDiscoRead.Enabled:= True;
end;

procedure TfrmPrincipal.LeyendoMemoria;
begin
  imgMemoriaRead.Enabled:= True;
end;

function GenerarListaProcesos: tListaProcesos;
var
  proceso: tProceso;
  identificador, x: Integer;
  lstProc: tListaProcesos;
const
// Datos utilizados en las clases
  datos: Array[1..5, 1..2] of Integer = ((0,3),(1,5),(4,2),(5,6),(8,4));
// Otros datos de prueba
//  datos: Array[1..5, 1..2] of Integer = ((0,3),(4,3),(14,6),(1,3),(8,2));
begin
  identificador:= 0;
  lstProc:= tListaProcesos.Create;
  for x:= 1 to 5 do
  begin
    proceso:= tProceso.Create;
    Inc(identificador);
    proceso.id:= identificador;
    proceso.Iniciado:= datos[x,1];
    proceso.Duracion:= datos[x,2];
    proceso.Realizado:= 0;
    lstProc.Add(proceso);
  end;
  result:= lstProc;
end;

procedure TfrmPrincipal.btnIniciarClick(Sender: TObject);
begin
  btnIniciar.Enabled:= False;
  if mnuRR.Checked then
    quantumG:= StrToInt(InputBox('Quantum para Round Robin','Ingrese el valor de Quantum', '3'));
  // Instanciar el Manejador de Procesos
  todosLosProcesosA:= tListaProcesos.Create;
  todosLosProcesosC:= tListaProcesos.Create;
  pManagerAlumno:= tManejadorProcesadorAlumno.Create(todosLosProcesosA);
  pManagerCatedra:= tManejadorProcesadorCatedra.Create(todosLosProcesosC);
  todosLosProcesosC:= GenerarListaProcesos;
  todosLosProcesosA:= GenerarListaProcesos;
  InicializarGrilla(gProcesosC, todosLosProcesosC);
  InicializarGrilla(gProcesosA, todosLosProcesosA);
  // Inicia la CPU
  ciclo:= -1;
  pActualAlumno:= nil;
  pActualCatedra:= nil;
  cpuClock.Enabled:= True;
end;

procedure TfrmPrincipal.FormCreate(Sender: TObject);
begin
  // Creo el Hardware necesario
  procesador:= tProcesador.Create(thProcesador, 'Intel', 'Pentium IV 3.2 GHz'); // No vamos a bajar costos poniendo otra cosa !!!! :-P
  memoria:= tMemoria.Create(thMemoria, 'Kingston', 'DDR2 633MHz');
  disco:= tDisco.Create(thDiscoRigido, 'Wenster Digital', 'SCSI 15000rpm 200 Gb');
end;

procedure TfrmPrincipal.cpuClockTimer(Sender: TObject);
var
  x: Integer;
begin
  Inc(Ciclo);
  // Busco los procesos que se deben ejecutar en el siguiente ciclo
  for x:= 0 to todosLosProcesosC.Count - 1 do
    if tProceso(todosLosProcesosC.Items[x]).Iniciado = Ciclo then
      begin
      pManagerAlumno._procesos.Add(todosLosProcesosA.Items[x]);
      pManagerCatedra._procesos.Add(todosLosProcesosC.Items[x]);
      end;
  if ciclo <= TiempoTotal then
    begin
    gProcesosC.Cells[ciclo + 1, 0]:= intToStr(ciclo);
    gProcesosA.Cells[ciclo + 1, 0]:= intToStr(ciclo);
    if mnuFIFO.Checked then
      begin
      pActualAlumno:= pManagerAlumno.FIFO(pManagerAlumno._procesos, pActualAlumno, ciclo);
      pActualCatedra:= pManagerCatedra.FIFO(pManagerCatedra._procesos, pActualCatedra, ciclo);
      end
    else
      if mnuRR.Checked then
        begin
        pActualAlumno:= pManagerAlumno.RR(pManagerAlumno._procesos, pActualAlumno, quantumG, ciclo);
        pActualCatedra:= pManagerCatedra.RR(pManagerCatedra._procesos, pActualCatedra, quantumG, ciclo);
        end
      else
        if mnuSJN.Checked then
          begin
          pActualAlumno:= pManagerAlumno.SJN(pManagerAlumno._procesos, pActualAlumno, ciclo);
          pActualCatedra:= pManagerCatedra.SJN(pManagerCatedra._procesos, pActualCatedra, ciclo);
          end
        else
          if mnuSRT.Checked then
            begin
            pActualAlumno:= pManagerAlumno.SRT(pManagerAlumno._procesos, pActualAlumno, ciclo);
            pActualCatedra:= pManagerCatedra.SRT(pManagerCatedra._procesos, pActualCatedra, ciclo);
            end;
    // Recorrer la lista para graficar las esperas
    for x:= 0 to pManagerCatedra._procesos.Count -1 do
      if (tProceso(pManagerCatedra._procesos.items[x]).Iniciado <= ciclo) then
        gProcesosC.Cells[ciclo + 1, tProceso(pManagerCatedra._procesos.items[x]).id]:= 'E';
    for x:= 0 to pManagerAlumno._procesos.Count -1 do
      if (tProceso(pManagerAlumno._procesos.items[x]).Iniciado <= ciclo) then
         gProcesosA.Cells[ciclo + 1, tProceso(pManagerAlumno._procesos.items[x]).id]:= 'E';
    // Procesar
    if pActualCatedra <> nil then
      gProcesosC.Cells[ciclo + 1, pActualCatedra.id]:= '-';
    if pActualAlumno <> nil then
      gProcesosA.Cells[ciclo + 1, pActualAlumno.id]:= '-';
    end
  else
    begin
    btnIniciar.Enabled:= True;
    cpuClock.Enabled:= False;
    end;
end;

procedure TfrmPrincipal.gProcesosCDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
with Sender as TDrawGrid do
	begin
		if (ACol = 0) or (ARow = 0) then
			Exit //Canvas.Brush.Color:= clBtnFace
		else if (Sender as TStringGrid).Cells[ACol, ARow] <> '' then
			case (Sender as TStringGrid).Cells[ACol, ARow][1] of
				'E': // Procesado por Alumnos
          begin
					Canvas.Brush.Color:= clSkyBlue;
          Canvas.FillRect(Rect);
          end;
				'-': // Procesado por Simulador (profes)
          begin
					Canvas.Brush.Color:= clRed;
          Canvas.FillRect(Rect);
          end;
				else
          begin
					Canvas.Brush.Color:= clWindow;
          Canvas.FillRect(Rect);
          end;
			end;
	end;
end;

procedure TfrmPrincipal.acClickAlgoritmoExecute(Sender: TObject);
var
  lista: TList;
  x: Integer;
begin
  // Click en alguno de los Items del Menu que marcan el tipo de
  // algoritmo a ejecutar
  lista:= TList.Create;
  lista.Add(mnuFIFO); lista.Add(mnuSJN); lista.Add(mnuRR); lista.Add(mnuSRT);
  for x:= 0 to lista.Count -1 do
    if TMenuItem(lista.Items[x]) = TMenuItem(Sender) then
      TMenuItem(lista.Items[x]).Checked:= True
    else
      TMenuItem(lista.Items[x]).Checked:= False;
end;

procedure TfrmPrincipal.InicializarGrilla(laGrilla: TStringGrid;
  listaProcesos: tListaProcesos);
var
  x, y: Integer;
begin
  laGrilla.ColCount:= 0;
  laGrilla.RowCount:= 0;
  laGrilla.Refresh;
  laGrilla.ColCount:= TiempoTotal + 1;
  laGrilla.RowCount:= listaProcesos.Count + 1;
  laGrilla.FixedCols:= 1;
  laGrilla.FixedRows:= 1;
  for x:= 0 to listaProcesos.Count -1 do
    laGrilla.cells[0, x + 1]:= intToStr(tProceso(listaProcesos.items[x]).id);
  for x:= 1 to listaProcesos.Count do
    for y:= 1 to TiempoTotal do
      laGrilla.Cells[y, x]:= '';
end;

end.
